﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace YoderSolutions.Libs.Extensions.Dictionary
{
    public static class DictionaryExtensions
    {
        /// <summary>
        /// Performs an action on each KeyValuePair in a dictionary
        /// </summary>
        /// <typeparam name="key">Key Type</typeparam>
        /// <typeparam name="value">Value Type</typeparam>
        /// <param name="dictionary"></param>
        /// <param name="action">Action to perform</param>
        public static void ForEach<keyType, valueType>(this Dictionary<keyType, valueType> dictionary, Action<keyType, valueType> action)
        {
            foreach (KeyValuePair<keyType,valueType> kvp in dictionary)
                action(kvp.Key, kvp.Value);
        }

        /// <summary>
        /// Returns the sum of the returned values from the Func delegate
        /// </summary>
        /// <typeparam name="keyType">Key Type</typeparam>
        /// <typeparam name="valueType">Value Type</typeparam>
        /// <param name="dictionary"></param>
        /// <param name="func">Function to perform on each KeyValuePair</param>
        /// <returns>Sum of the returned values from the Func delegate</returns>
        public static int Sum<keyType, valueType>(this Dictionary<keyType, valueType> dictionary, Func<keyType, valueType, int> func)
        {
            int sum = 0;
            foreach (KeyValuePair<keyType,valueType> kvp in dictionary)
                sum += func(kvp.Key, kvp.Value);
            return sum;
        }

        /// <summary>
        /// Returns the sum of the returned values from the Func delegate
        /// </summary>
        /// <typeparam name="keyType">Key Type</typeparam>
        /// <typeparam name="valueType">Value Type</typeparam>
        /// <param name="dictionary"></param>
        /// <param name="func">Function to perform on each KeyValuePair</param>
        /// <returns>Sum of the returned values from the Func delegate</returns>
        public static double Sum<keyType, valueType>(this Dictionary<keyType, valueType> dictionary, Func<keyType, valueType, double> func)
        {
            double sum = 0;
            foreach (KeyValuePair<keyType, valueType> kvp in dictionary)
                sum += func(kvp.Key, kvp.Value);
            return sum;
        }

        /// <summary>
        /// Returns a formatted string displaying the key/value pairs within the dictionary
        /// </summary>
        /// <remarks>
        /// Example of formatted string
        /// [key1: value1][key2: value2]
        /// </remarks>
        /// <typeparam name="keyType">Key Type</typeparam>
        /// <typeparam name="valueType">Value Type</typeparam>
        /// <param name="dictionary"></param>
        /// <returns>Formatted string displaying the key/value pairs within the dictionary</returns>
        public static string ToKeyValueString<keyType, valueType>(this Dictionary<keyType, valueType> dictionary)
        {
            StringBuilder formattedString = new StringBuilder();
            foreach (KeyValuePair<keyType,valueType> kvp in dictionary)
                formattedString.Append("[" + kvp.Key.ToString() + ": " + kvp.Value.ToString() + "]");
            return formattedString.ToString();
        }

        /// <summary>
        /// Returns a formatted string displaying the key/value pairs within the dictionary
        /// </summary>
        /// <typeparam name="keyType">Key Type</typeparam>
        /// <typeparam name="valueType">Value Type</typeparam>
        /// <param name="dictionary"></param>
        /// <returns>Formatted string displaying the key/value pairs within the dictionary</returns>
        public static string ToKeyValueString<keyType, valueType>(this Dictionary<keyType, valueType> dictionary, Func<keyType, valueType, string> func)
        {
            StringBuilder formattedString = new StringBuilder();
            foreach (KeyValuePair<keyType, valueType> kvp in dictionary)
                formattedString.Append("[" + func(kvp.Key,kvp.Value) + "]");
            return formattedString.ToString();
        }
    }
}
